﻿using DBInStudio.Desktop;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Input;

namespace MarsUniformApiExample
{
    /// <summary>
    /// 
    /// </summary>
    public class HighSpeedApiTestViewModel : ModelBase
    {
        #region ... Variables  ...
        private string mIp = "127.0.0.1";
        private ICommand mConnectCommand;
        private ICommand mStopCommand;
        private List<TagItemInfo> mTags = new List<TagItemInfo>();
        //DBHighApi.HighSpeedApiClient clinet;
        private Thread mScanThread;
        private bool mExited = false;

        private ICommand mSetTagValueCommand;

        private List<int> mIds;

        private MarsUniformApi.MarsApi mClient;

        private ICommand mQueryHisCommand;

        private ICommand mQueryHisCommand2;

        #endregion ...Variables...

        #region ... Events     ...

        #endregion ...Events...

        #region ... Constructor...
        /// <summary>
        /// 
        /// </summary>
        public HighSpeedApiTestViewModel()
        {
        }
        #endregion ...Constructor...


        #region ... Properties ...

        public MarsUniformApi.MarsApi Client { get { return mClient; } set { mClient = value; Init(); } }

        /// <summary>
        /// 
        /// </summary>
        public List<TagItemInfo> Tags
        {
            get
            {
                return mTags;
            }
        }


        /// <summary>
        /// 
        /// </summary>
        public string Ip
        {
            get
            {
                return mIp;
            }
            set
            {
                if (mIp != value)
                {
                    mIp = value;
                    OnPropertyChanged("Ip");
                }
            }
        }

        public ICommand ConnectCommand
        {
            get
            {
                if (mConnectCommand == null)
                {
                    mConnectCommand = new RelayCommand(() =>
                    {
                        Connect();
                    }, () => { return mClient!=null && mClient.IsConsumerConnected(); });
                }
                return mConnectCommand;
            }
        }

        /// <summary>
        /// 
        /// </summary>
        public ICommand StopCommand
        {
            get
            {
                if (mStopCommand == null)
                {
                    mStopCommand = new RelayCommand(() => {
                        mExited = true;
                        //clinet.Close();

                    });
                }
                return mStopCommand;
            }
        }

        /// <summary>
        /// Id
        /// </summary>
        public int Id { get; set; }

        /// <summary>
        /// Value
        /// </summary>
        public double Value { get; set; }

        /// <summary>
        /// 
        /// </summary>
        public ICommand SetTagValueCommand
        {
            get
            {
                if (mSetTagValueCommand == null)
                {
                    mSetTagValueCommand = new RelayCommand(() => {

                        Client.SetTagValueForConsumer(Id, (int)(Cdy.Tag.TagType.Double), Value);
                    });
                }
                return mSetTagValueCommand;
            }
        }

        public ICommand QueryHisCommand
        {
            get
            {
                if(mQueryHisCommand == null)
                {
                    mQueryHisCommand = new RelayCommand(() => {
                        QueryHisValue(Id, mHisStartTime,mHisEndTime);
                    });
                }
                return mQueryHisCommand;
            }
        }

        /// <summary>
        /// 
        /// </summary>
        public ICommand QueryHisCommand2
        {
            get
            {
                if (mQueryHisCommand2 == null)
                {
                    mQueryHisCommand2 = new RelayCommand(() => {
                        QueryHisValue2(Id, mHisStartTime, mHisEndTime);
                    });
                }
                return mQueryHisCommand2;
            }
        }

        private bool mIsAllHisValue = true;
        /// <summary>
        /// 
        /// </summary>
        public bool IsAllHisValue
        {
            get
            {
                return mIsAllHisValue;
            }
            set
            {
                if (mIsAllHisValue != value)
                {
                    mIsAllHisValue = value;
                    OnPropertyChanged("IsAllHisValue");
                }
            }
        }

        private DateTime mHisStartTime=DateTime.Now.Date.AddDays(-1);
        /// <summary>
            /// 
            /// </summary>
        public DateTime HisStartTime
        {
            get
            {
                return mHisStartTime;
            }
            set
            {
                if (mHisStartTime != value)
                {
                    mHisStartTime = value;
                    OnPropertyChanged("HisStartTime");
                }
            }
        }
        private DateTime mHisEndTime=DateTime.Now.Date;
        /// <summary>
        /// 
        /// </summary>
        public DateTime HisEndTime
        {
            get
            {
                return mHisEndTime;
            }
            set
            {
                if (mHisEndTime != value)
                {
                    mHisEndTime = value;
                    OnPropertyChanged("HisEndTime");
                }
            }
        }

        private ICommand mClearRegistorCommand;
        public ICommand ClearRegistorCommand
        {
            get
            {
                if(mClearRegistorCommand==null)
                {
                    mClearRegistorCommand = new RelayCommand(() => {
                        bool re = Client.ClearRegistorTagValueCallBack(new List<int> { 0, 1 });
                    });
                }
                return mClearRegistorCommand;
            }
        }


        #endregion ...Properties...

        #region ... Methods    ...

        private void Connect()
        {
            Task.Run(() => {
                bool re = Client.RegistorTagValueCallBack(0,1);
                if(!re)
                {
                    MessageBox.Show("注册失败！");
                }
                InitFunTest();
                //mScanThread = new Thread(ScanProcess);
                //mScanThread.IsBackground = true;
                //mScanThread.Start();
            });
        }

        /// <summary>
        /// 
        /// </summary>
        private void Init()
        {
            mIds = new List<int>();
            mTags.Clear();
            mIds.Clear();

            if (Client == null) return;
        
            for (int i = 0; i < 100000; i++)
            {
                mTags.Add(new TagItemInfo() { Id = i, Value = "0" });
                mIds.Add(i);
            }
            //clinet = new DBHighApi.HighSpeedApiClient();
            Client.SetTagValueChangedCallBackForConsumer( (val) =>
            {
                foreach (var vv in val)
                {
                    if (vv.Key < mTags.Count)
                        mTags[vv.Key].Value = vv.Value.Item1.ToString();
                }
            });
            Client.PropertyChanged += Clinet_PropertyChanged;
        }

        private void Clinet_PropertyChanged(object sender, PropertyChangedEventArgs e)
        {
            if (e.PropertyName == "IsConnected")
            {
                if (Client!=null&&Client.IsConsumerConnected())
                {
                   

                }
            }
        }

        private void InitFunTest()
        {
            var ids = Client.GetTagIdsForConsumer(new List<string>() { "Double.Double1" });
            var tags = Client.ListAllTagForConsumer();
            var grps = Client.ListALlTagGroupForConsumer();
            Client.ListTagByGroupForConsumer("Double");
        }

        /// <summary>
        /// 
        /// </summary>
        private void ScanProcess()
        {
            while (!mExited)
            {
                UpdateValue();
                Thread.Sleep(500);
            }
        }

        /// <summary>
        /// 
        /// </summary>
        private void UpdateValue()
        {
            //if (!clinet.IsLogin)
            //{
            //    clinet.Login("Admin", "Admin");
            //    return;
            //}
            Stopwatch sw = new Stopwatch();
            sw.Start();

            var vals = Client.GetRealDataValueAndQualityOnlyForConsumer(mIds, true);
            sw.Stop();
            Debug.WriteLine($"time : { sw.ElapsedMilliseconds }");
            if (vals != null)
            {
                for (int i = 0; i < 50000; i++)
                {
                    if (vals.ContainsKey(i))
                        mTags[i].Value = vals[i].Item1?.ToString();
                }
            }

            sw.Restart();

            var avals = Client.GetRealDataForConsumer(mIds, true);
            sw.Stop();
            Debug.WriteLine($"time : { sw.ElapsedMilliseconds }");
            if (avals != null)
            {
                for (int i = 0; i < 50000; i++)
                {
                    if (avals.ContainsKey(i))
                        mTags[i].Value = avals[i].Item1?.ToString();
                }
            }


            sw.Restart();

            var aqvals = Client.GetRealDataValueAndQualityOnlyForConsumer(mIds, true);
            sw.Stop();
            Debug.WriteLine($"time : { sw.ElapsedMilliseconds }");
            if (aqvals != null)
            {
                for (int i = 0; i < 50000; i++)
                {
                    if (aqvals.ContainsKey(i))
                        mTags[i].Value = aqvals[i].Item1?.ToString();
                }
            }
        }


        private void QueryHisValue(int id,DateTime statetime,DateTime endtime)
        {
            string sdir = System.IO.Path.Combine(System.IO.Path.GetDirectoryName(this.GetType().Assembly.Location),DateTime.Now.Ticks.ToString()+".txt");
            using (var ss = new System.IO.StreamWriter(System.IO.File.OpenWrite(sdir)))
            {
                if (mIsAllHisValue)
                {
                    var his = Client.QueryAllHisValue<double>(id, statetime, endtime);
                    if (his != null)
                    {
                        foreach (var vv in his.ListAvaiableValues())
                        {
                            ss.WriteLine(vv.Time + ":" + vv.Value);
                            // Console.WriteLine(vv.Value);
                        }
                        //for(int i = 0; i < his.Count; i++)
                        //{
                        //    Console.WriteLine(his.GetValue(i));
                        //}
                    }
                }
                else
                {
                    var his = Client.QueryHisValueForTimeSpan<double>(id, statetime, endtime, new TimeSpan(0, 0, 10), Cdy.Tag.QueryValueMatchType.Previous);
                    if (his != null)
                    {
                        foreach (var vv in his.ListAvaiableValues())
                        {
                            ss.WriteLine(vv.Time +":"+vv.Value);
                            //Console.WriteLine(vv.Value);
                        }
                        //for(int i = 0; i < his.Count; i++)
                        //{
                        //    Console.WriteLine(his.GetValue(i));
                        //}
                    }
                }
            }

            Process.Start(sdir);
        }


        private void QueryHisValue2(int id, DateTime statetime, DateTime endtime)
        {
            string sdir = System.IO.Path.Combine(System.IO.Path.GetDirectoryName(this.GetType().Assembly.Location), DateTime.Now.Ticks.ToString() + ".txt");
            using (var ss = new System.IO.StreamWriter(System.IO.File.OpenWrite(sdir)))
            {
                if (mIsAllHisValue)
                {
                    var his = Client.QueryAllHisValue<double>(id, statetime, endtime);
                    if (his != null)
                    {
                        foreach (var vv in his.ListAvaiableValues())
                        {
                            ss.WriteLine(vv.Time + ":" + vv.Value);
                            // Console.WriteLine(vv.Value);
                        }
                        //for(int i = 0; i < his.Count; i++)
                        //{
                        //    Console.WriteLine(his.GetValue(i));
                        //}
                    }
                }
                else
                {
                    var his = Client.QueryHisValueForTimeSpanByIgnorSystemExit<double>(id, statetime, endtime, new TimeSpan(1, 0, 0), Cdy.Tag.QueryValueMatchType.Previous,60000);
                    if (his != null)
                    {
                        //int i = 0;
                        ss.WriteLine($"查询值的数量:{his.Count}");
                        //foreach (var vv in his.ListAvaiableValues())
                        //{
                        //    ss.WriteLine(i+"  "+ vv.Time + " : " + vv.Value);
                        //    i++;
                        //    //Console.WriteLine(vv.Value);
                        //}
                        for (int i = 0; i < his.Count; i++)
                        {
                            var vv = his.GetValue(i,out DateTime time,out byte qua);

                            ss.WriteLine(i +" " + vv + "  " + time + "  " + qua);
                        }
                    }
                }
            }

            Process.Start(sdir);
        }

        #endregion ...Methods...

        #region ... Interfaces ...

        #endregion ...Interfaces...
    }


    public class TagItemInfo : ModelBase
    {
        private string mValue;
        public int Id { get; set; }

        public string Value { get { return mValue; } set { mValue = value; OnPropertyChanged("Value"); } }

    }


    /// <summary>
    /// 
    /// </summary>
    public class ModelBase : INotifyPropertyChanged
    {
        public event PropertyChangedEventHandler PropertyChanged;

        protected void OnPropertyChanged(string name)
        {
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(name));
        }
    }
}
